//
//  ES1Renderer.m
//  iPadStencilTest
//
//  Created by Goffredo Marocchi on 8/19/10.
//  Copyright IGGS 2010. All rights reserved.
//

#import "ES1Renderer.h"
#import "___PROJECTNAMEASIDENTIFIER___Template.h"
#import "sio2.h"

extern int tmp_argc;
extern char **tmp_argv;

SIO2* sio2Ptr;

@implementation ES1Renderer

// Create an OpenGL ES 1.1 context
- (id)init
{
    if ((self = [super init]))
    {
        context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1];

        if (!context || ![EAGLContext setCurrentContext:context])
        {
            [self release];
            return nil;
        }
		
        // Create default framebuffer object. The backing will be allocated for the current layer in -resizeFromLayer
        glGenFramebuffersOES(1, &defaultFramebuffer);
        glGenRenderbuffersOES(1, &colorRenderbuffer);
        glBindFramebufferOES(GL_FRAMEBUFFER_OES, defaultFramebuffer);
        glBindRenderbufferOES(GL_RENDERBUFFER_OES, colorRenderbuffer);
        glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, colorRenderbuffer);
		
		isSimulator = ( 0 == strcmp ((const char*)"Apple Software Renderer", 
										   (const char*) glGetString(GL_RENDERER)) )?TRUE:FALSE;
		displayLinkSupported = DISPLAY_LINK;
		
		printf("\nWe are running on the iOS %s\n", (isSimulator?"simulator":"device"));
		
    }

    return self;
}


- (BOOL)resizeFromLayer:(CAEAGLLayer *)layer
{	
    // Allocate color buffer backing based on the current layer size
    glBindRenderbufferOES(GL_RENDERBUFFER_OES, colorRenderbuffer);
    [context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:layer];
    glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth);
    glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight);
	
	if (isSimulator) {
		
		NSLog(@"Simulator path");
		
		glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth);
		glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight);
		
		glGenRenderbuffersOES(1, &depthRenderbuffer);
		glBindRenderbufferOES(GL_RENDERBUFFER_OES, depthRenderbuffer);
		glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_DEPTH_COMPONENT24_OES, backingWidth, backingHeight);
		glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer);
		
		glGenRenderbuffersOES(1, &stencilRenderbuffer);
		glBindRenderbufferOES(GL_RENDERBUFFER_OES, stencilRenderbuffer);
		glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_STENCIL_INDEX8_OES, backingWidth, backingHeight);
		glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_STENCIL_ATTACHMENT_OES, GL_RENDERBUFFER_OES, stencilRenderbuffer);
	}
	else {
		
		NSLog(@"Device path");

		glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth);
		glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight);
		
		glGenRenderbuffersOES(1, &depthStencilBuffer);
		glBindRenderbufferOES(GL_RENDERBUFFER_OES, depthStencilBuffer);
		glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_DEPTH24_STENCIL8_OES, backingWidth, backingHeight);
		glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthStencilBuffer);
		glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_STENCIL_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthStencilBuffer);
	}

    if (glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES)
    {
        NSLog(@"Failed to make complete framebuffer object %x", glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES));
        return NO;
    }
	
	if( !sio2 )
	{
		// Initialize SIO2 global variable
		sio2Init( &tmp_argc, tmp_argv );
		
		// Initialize OpenGL ES
		sio2InitGL();
		
		// Initialize OpenAL
		//sio2InitAL();
		
		sio2Ptr = sio2;
		
		// Create a window using the default sio2 structure handle
		sio2->_SIO2window = sio2WindowInit();
		
		sio2->_SIO2resource = sio2ResourceInit((char*) "default" );
		// Update the viewport with the current window size
		sio2WindowUpdateViewport( sio2->_SIO2window, 0, 0, backingWidth, backingHeight );
		
		// Attach a function to the render callback
		//sio2->_SIO2window->_SIO2windowrender = templateRender;
		sio2->_SIO2window->_SIO2windowrender = templateLoader;
		
		// Specify the function callback to use when the application quit.
		sio2WindowShutdown( sio2->_SIO2window, templateShutdown );
		
		// Link the appropriate callbacks to handle tap, move and the
		// accelerometer.
		sio2->_SIO2window->_SIO2windowtap			= templateScreenTap;
		sio2->_SIO2window->_SIO2windowtouchmove		= templateScreenTouchMove;
		sio2->_SIO2window->_SIO2windowaccelerometer = templateScreenAccelerometer;
		
	}

    return YES;
}

- (void)renderSIO2:(id)displayLink {	
    // This application only creates a single context which is already set current at this point.
    // This call is redundant, but needed if dealing with multiple contexts.
    [EAGLContext setCurrentContext:context];
	
	
	if( sio2->_SIO2window->_SIO2windowrender )
	{
		sio2->_SIO2window->_SIO2windowrender();
		
		sio2WindowSwapBuffers( sio2->_SIO2window );
		if (displayLinkSupported && displayLink) sio2->_SIO2window->d_time = [displayLink duration];
	}
	
    // This application only creates a single default framebuffer which is already bound at this point.
    // This call is redundant, but needed if dealing with multiple framebuffers.
    //glBindFramebufferOES(GL_FRAMEBUFFER_OES, defaultFramebuffer); //currently using a single framebuffer

    glBindRenderbufferOES(GL_RENDERBUFFER_OES, colorRenderbuffer);
    [context presentRenderbuffer:GL_RENDERBUFFER_OES];
}

- (void)dealloc
{
    // Tear down GL
    if (defaultFramebuffer)
    {
        glDeleteFramebuffersOES(1, &defaultFramebuffer);
        defaultFramebuffer = 0;
    }

    if (colorRenderbuffer)
    {
        glDeleteRenderbuffersOES(1, &colorRenderbuffer);
        colorRenderbuffer = 0;
    }
	
	if(depthRenderbuffer) {
		glDeleteRenderbuffersOES(1, &depthRenderbuffer);
		depthRenderbuffer = 0;
	}
	if(stencilRenderbuffer) {
		glDeleteRenderbuffersOES(1, &stencilRenderbuffer);
		stencilRenderbuffer = 0;
	}
	if(depthStencilBuffer) {
		glDeleteRenderbuffersOES(1, &depthStencilBuffer);
		depthStencilBuffer = 0;
	}

    // Tear down context
    if ([EAGLContext currentContext] == context)
        [EAGLContext setCurrentContext:nil];

    [context release];
    context = nil;

    [super dealloc];
}

@end
